Esercitazione 5
Esercizio 5.1: esame 2023-07-18
Qui testo e soluzione.
Provare a svolgere da sé l'esercizio, prima di guardare la soluzione o andare oltre per la discussione.
Il corretto pilotaggio di interfacce parallele richiede inevitabilmente più stati di quanto è solito usare per esercizi, per esempio, con handshake dav_/rfd o soc/eoc.
Per questo, sono tipicamente gli esercizi che hanno più tempo a disposizione in sede d'esame.
In questo esercizio si lavora con interfacce parallele connesse ad un bus, una interfaccia di ingresso con handshake (da cui ottenere dati in ingresso) ed una interfaccia di ingresso e uscita senza handshake (a cui scrivere il risultato del calcolo). Il calcolo da svolgere è semplice: bisogna moltiplicare l'ingresso per 5, esprimendo il risultato su 16 bit. È opzionale sintetizzarlo con rete combinatoria.
La parte critica dell'esercizio è il corretto pilotaggio del bus, evitando corse critiche e usando potre tri-state per evitare situazioni di corto circuito, e delle interfacce.
Per quanto riguarda le operazioni sul bus, ricordiamo che le interfacce si attivano alla ricezione di segnali ior_
e iow_
.
Questi segnali arrivano a tutte le interfacce sul bus, ma è solo quella selezionata tramite addr
che si attiva, o leggendo data
o assegnandogli un valore.
È quindi critico che i fili di uscita addr
e data
siano stabili prima di portare ior_
o iow_
a 0.
Per data
, questo si traduce, per scritture, nel valore assegnato stabile (per esempio, con registro DATA
) e la porta tri-state abilitata (solitamente, DIR = 1
); per le letture invece si disabilita la porta tri-state (solitamente, DIR = 0
) per lasciare che sia l'interfaccia a assegnargli un valore.
Ricordiamo che il problema qui è di tipo elettrico: assegnare un valore logico ad un filo equivale a imporre una tensione, e se più dispositivi assegnano tensioni diverse sullo stesso filo la differenza di potenziale porta ad un disastroso corto circuito.
Questo schema di pilotaggio va ripetuto più volte per accedere ai diversi registri.
L'interfaccia parallela di ingresso con handshake richiede che si legga il suo registro RSR
, ed in particolare il suo flag FI
, in attesa che FI = 1
segnali la presenza di un dato da poter leggere.
La lettura verrà fatta sul registro RBR
.
Per l'interfaccia parallela di ingresso-uscita senza handshake, dovremo invece fare due scritture sul registro TBR
.
Esercizio 5.1: esame 2024-01-26
Qui testo e soluzione.
Provare a svolgere da sé l'esercizio, prima di guardare la soluzione o andare oltre per la discussione.
Il testo di questo esercizio è pensato per apparire fuori dalla norma a un occhio poco preparato, ma si rivela molto semplice con le dovute osservazioni.
Tralasciando le curiosità sulla congettura di Collatz, ciò che ci interessa è osservare che il calcolo di a partire da è di tipo combinatorio. Ciò è anche suggerito dal testo, che ci chiede di sintetizzare proprio questo.
Ciò che non è combinatorio è invece il calcolo di a partire da : questa è infatti una operazione iterativa, che implica una struttura ad anello che svolge più passaggi. Come dovremmo ben sapere, tali anelli non possono essere reti combinatorie, e vanno invece implementate con reti sincronizzate che avanzano a passaggi discreti guidati dal segnale del clock. Anche questa osservazione è suggerita dal testo, visto che il modo più immediato per ottenere è contare le iterazioni necessarie per arrivare ad 1.
La struttura chiave quindi è la seguente: abbiamo un registro N
che conterrà l'attuale , inizializzato con . Al posedge del clock, campionando l'uscita della rete combinatoria CALCOLO_ITERAZIONE
, riceve il nuovo valore .
Contemporaneamente, un registro K
, inizializzato a 0, conta con K <= K + 1;
quanti posedge sono necessari perché N
arrivi ad 1.
Questo è garantito dall'uso di un cambio di stato che interrompe il conteggio quando la condizione è raggiunta, fatte le solite osservazioni per il corretto conteggio di cicli di clock.
Questo ciclo può essere espresso come nel seguente pseudo-codice:
...
CALCOLO_ITERAZIONE ci(
.n_curr(N),
.n_next(n_next)
);
...
always @(posedge clock) if(reset_ == 1) #3 begin
casex(STAR)
...
S_init: begin
N <= n_0;
K <= 0;
...
end
S_loop: begin
N <= n_next;
K <= K + 1;
STAR <= (n_next == 1) ? S_after : S_loop;
end
S_after: ...
endcase
end
...
Una volta chiarito questo processo, il resto dell'esercizio è molto semplice.
Va dimensionato N
e la relativa rete combinatoria: il testo ci indica che il massimo raggiungibile è inferiore a 'h4000
, implicando che 14 bit sono sufficienti.
Va poi sintetizzata la rete combinatoria, che altro non è che un multiplexer, guidato dal bit meno significativo, i cui due ingressi sono uno shift a destra e un moltiplicatore con y = 3
e c = 1
.
Infine, la rete sincronizzata campiona n_0
e invia k
tramite un singolo handshake soc/eoc.
Nota di colore su bug assurdi
Questa pagina è stata scritta la mattina del 6 Dicembre prima dell'esercitazione dove ho lasciato questi due esercizi da svolgere. Durante l'esercitazione, cercando di mostrarlo per una domanda a riguardo, mi sono casualmente accorto che il sito era rotto. Ho quindi cercato, tra una domanda e l'altra, di debuggare il sito per rimettere tutto il resto e questa pagina online prima della fine dell'esercitazione.
Questo sito usa Docusaurus, un framework che permette di scrivere documentazione in semplice markdown che viene poi tradotto in HTML. Le pagine di queste esercitazioni sono organizzate in cartelle e file markdown così
- Assembler
- Documentazione
- Esercitazioni
...
- Verilog
- Documentazione
- Esercitazioni
- 1. Esercitazione 1.mdx
- 2. Esercitazione 2.mdx
- 3. Esercitazione 3.mdx
- 4. Esercitazione 4.mdx
- 5. Esercitazione 5.mdx
...
Visto che fino a 4. Esercitazione 4.mdx
ha funzionato tutto mentre con 5. Esercitazione 5.mdx
no, ho passato gran parte del tempo a cercare di capire come gli errori (assurdi) fossero causati da qualche problema nel file.
Alla fine, ho scoperto che bastava cambiare il nome.
Così funziona, anche se non ho idea del perché. Qui il bug report.